import sys
from multiprocessing import Process

from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QThread, Qt

from Ui_hmi_qt import Ui_Dialog


COLOR_RED   = "color:rgb(255,0,0)"
COLOR_BLUE  = "color:rgb(0,0,255)"
COLOR_GRAY  = "color:gray"
COLOR_BLACK = "color:black"
COLOR_WHITE = "color:white"
COLOR_GREEN = "color:green"
COLOR_ORANGE = "color:orange"
COLOR_YELLOW = "color:yellow"

CMD_UPDATE_STA  = 0
CMD_UPDATE_TEMP = 1
CMD_UPDATE_MC = 2

TEMP_HOTEND = 0
TEMP_BED    = 1

STA_UNCONNECTED     = 0
STA_CONNECTED       = 1
STA_TESTING         = 2
STA_DISCONNECTED    = 3
STA_TEST_PASS       = 4
STA_NO_MC           = 5
STA_NO_EXECUTOR     = 6
STA_BAD_BED_PORT    = 7
STA_EXCTR_HEATED_FAIL = 8
STA_BED_HEATED_FAIL = 9
STA_VERSION_ERROR   = 10
STA_EXCTR_TYPE_ERR  = 11
STA_SET_TEMP_ERR    = 12
STA_MEASURE_TEMP_ERR = 13
STA_MEASURE_EXCTR_ERR = 14
STA_MEASURE_BED_ERR = 15
STA_HEATED_FAIL = 16
STA_PROCESS_DEAD = 17
STA_TEST_FAIL = 18
STA_HOMING = 19
STA_NO_LINEAR = 20
STA_NO_MODEL = 21
STA_NO_USB_STICK = 22
STA_NO_CHAMBER = 23
STA_UPDATE_DEFAULT_MC = 24
STA_FAIL_UPDATE_MC = 25
STA_HOMING_ADDON = 26
STA_REMAP_ADDON = 27
STA_REMAP_DEFAULT = 28
STA_MAX = 29


class HmiQt(QWidget):
    MAX_CHANNEL = 3

    sta_info = [x for x in range(0, STA_MAX)]
    sta_info[STA_UNCONNECTED] = "等待连接"
    sta_info[STA_CONNECTED] = "已连接，主控启动中"
    sta_info[STA_TESTING] = "测试中。。。"
    sta_info[STA_DISCONNECTED] = "已断开"
    sta_info[STA_TEST_PASS] = "测试通过"
    sta_info[STA_NO_MC] = "主控启动失败:F100"
    sta_info[STA_NO_EXECUTOR] = "识别不到执行头:F101"
    sta_info[STA_BAD_BED_PORT] = "热床端口损坏:F102"
    sta_info[STA_EXCTR_HEATED_FAIL] = "执行头加热失败:F103"
    sta_info[STA_BED_HEATED_FAIL] = "热床加热失败:F104"
    sta_info[STA_VERSION_ERROR] = "固件版本错误:F105"
    sta_info[STA_EXCTR_TYPE_ERR] = "执行头类型错误:F106"
    sta_info[STA_SET_TEMP_ERR] = "温度设置失败:F107"
    sta_info[STA_MEASURE_TEMP_ERR] = "热床和喷嘴测温异常:F108"
    sta_info[STA_MEASURE_EXCTR_ERR] = "喷嘴测温异常:F109"
    sta_info[STA_MEASURE_BED_ERR] = "热床测温异常:F110"
    sta_info[STA_HEATED_FAIL] = "执行头和热床加热失败:F111"
    sta_info[STA_PROCESS_DEAD] = "测试工具异常，请联系技术员！"
    sta_info[STA_TEST_FAIL] = "测试失败:F112"
    sta_info[STA_HOMING] = "模组正在回原点"
    sta_info[STA_NO_LINEAR] = "识别不到直线模组:F113"
    sta_info[STA_NO_MODEL] = "未识别到3根模组:F114"
    sta_info[STA_NO_USB_STICK] = "未识别到U盘:F115"
    sta_info[STA_NO_CHAMBER] = "未识别到外罩板:F119"
    sta_info[STA_UPDATE_DEFAULT_MC] = "升级出厂固件："
    sta_info[STA_FAIL_UPDATE_MC] = "升级固件失败"
    sta_info[STA_HOMING_ADDON] = "扩展口模组正在回原点"
    sta_info[STA_REMAP_ADDON] = "等待扩展口配置完成"
    sta_info[STA_REMAP_DEFAULT] = "等待8PIN口恢复"

    sta_color = [x for x in range(0, STA_MAX)]
    sta_color[STA_UNCONNECTED] = COLOR_BLACK
    sta_color[STA_CONNECTED] = COLOR_BLUE
    sta_color[STA_TESTING] = COLOR_BLUE
    sta_color[STA_DISCONNECTED] = COLOR_BLACK
    sta_color[STA_TEST_PASS] = COLOR_GREEN
    sta_color[STA_NO_MC] = COLOR_RED
    sta_color[STA_NO_EXECUTOR] = COLOR_RED
    sta_color[STA_BAD_BED_PORT] = COLOR_RED
    sta_color[STA_EXCTR_HEATED_FAIL] = COLOR_RED
    sta_color[STA_BED_HEATED_FAIL] = COLOR_RED
    sta_color[STA_VERSION_ERROR] = COLOR_RED
    sta_color[STA_EXCTR_TYPE_ERR] = COLOR_RED
    sta_color[STA_SET_TEMP_ERR] = COLOR_RED
    sta_color[STA_MEASURE_TEMP_ERR] = COLOR_RED
    sta_color[STA_MEASURE_EXCTR_ERR] = COLOR_RED
    sta_color[STA_MEASURE_BED_ERR] = COLOR_RED
    sta_color[STA_HEATED_FAIL] = COLOR_RED
    sta_color[STA_PROCESS_DEAD] = COLOR_RED
    sta_color[STA_TEST_FAIL] = COLOR_RED
    sta_color[STA_HOMING] = COLOR_BLUE
    sta_color[STA_NO_LINEAR] = COLOR_RED
    sta_color[STA_NO_MODEL] = COLOR_RED
    sta_color[STA_NO_USB_STICK] = COLOR_RED
    sta_color[STA_NO_CHAMBER] = COLOR_RED
    sta_color[STA_UPDATE_DEFAULT_MC] = COLOR_BLUE
    sta_color[STA_HOMING_ADDON] = COLOR_BLUE

    E_INV_CMD         = 0x0
    E_SUCCESS         = 0x1
    E_INV_ID_WIDGET   = 0x2
    E_INV_ID_PAGE     = 0x3
    E_INV_ID_PIC      = 0x4
    E_INV_ID_FONT     = 0x5
    E_FAIL_FILE_OP    = 0x6
    E_INV_CRC         = 0x9
    E_INV_BAUDRATE    = 0x11
    E_INV_ID_WAVE     = 0x12
    E_INV_VAR_NAME    = 0x1A
    E_INV_VAR_OP      = 0x1B
    E_INV_ASSIGN_OP   = 0x1C
    E_FAIL_EEPROM_OP  = 0x1D
    E_INV_PARAM_NUM   = 0x1E
    E_FAIL_IO_OP      = 0x1F
    E_FAIL_ESCAPE     = 0x20
    E_LONG_VAR_NAME   = 0x23
    E_FIFO_OVERFLOW   = 0x24

    TOUCH_EVENT_PRESSED  = 1
    TOUCH_EVENT_RELEASED = 0

    RET_TOUCH_AREA_EVENT    = 0X65
    RET_CURRENT_PAGE_ID     = 0X66
    RET_TOUCH_POSITION      = 0X67
    RET_TOUCH_WHEN_SLEEP    = 0X68
    RET_STR                 = 0X70
    RET_NUM                 = 0X71
    RET_DEV_SLEPT_AUTO      = 0X86
    RET_DEV_WAKUP_AUTO      = 0X87
    RET_DEV_BOOTUP          = 0X88
    RET_UPGRADING_WITH_SD   = 0X89
    RET_TRANSFER_DONE       = 0XFD
    RET_TRANSFER_READY      = 0XFE


    def __init__(self, parent=None):
        super().__init__(parent)

        # initalize UI
        self.__ui = Ui_Dialog()
        self.__ui.setupUi(self)
        #self.__ui.btn_status_ch1.setStyleSheet(COLOR_GREEN)
        self._current_status = STA_UNCONNECTED
        self._status_ui = [getattr(self.__ui, 'btn_status_ch{}'.format(i+1)) for i in range(self.MAX_CHANNEL)]
        self._temp_bed_ui = [getattr(self.__ui, 'btn_ch{}_temp_bed'.format(i+1)) for i in range(self.MAX_CHANNEL)]
        self._temp_nozzle_ui = [getattr(self.__ui, 'btn_ch{}_temp_nozzle'.format(i+1)) for i in range(self.MAX_CHANNEL)]
        self.process = None


    def update_mc(self, ch=0, percent=0):
        if ch >= self.MAX_CHANNEL:
            print("ch{0} is out of range: {1}".format(ch, self.MAX_CHANNEL))
            return
        self._current_status = CMD_UPDATE_MC
        self._status_ui[ch].setText(self.sta_info[STA_UPDATE_DEFAULT_MC]+"{}%".format(percent))
        

    def update_sta(self, ch=0, sta=STA_UNCONNECTED):
        if ch >= self.MAX_CHANNEL:
            print("ch{0} is out of range: {1}".format(ch, self.MAX_CHANNEL))
            return
        self._current_status = sta
        self._status_ui[ch].setText(self.sta_info[sta])

        if sta == STA_UNCONNECTED:
            self._temp_bed_ui[ch].setText("0 ℃")
            self._temp_nozzle_ui[ch].setText("0 ℃")


    def update_temp(self, ch=0, target=TEMP_HOTEND, temp=0):
        if ch >= self.MAX_CHANNEL:
            print("ch{0} is out of range: {1}".format(ch, self.MAX_CHANNEL))
            return

        if target == TEMP_HOTEND:
            self._temp_nozzle_ui[ch].setText("{} ℃".format(temp))
        else:
            self._temp_bed_ui[ch].setText("{} ℃".format(temp))
 

def process_hmi(app, ui):
    ui.show()
    sys.exit(app.exec_())


def start():
    app = QApplication(sys.argv)
    ui = HmiQt()
    ui.process = Process(target=process_hmi, name="hmi_qt", args=(app, ui))
    ui.process.start()
    return ui


def stop(ui):
    ui.process.terminate()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = HmiQt()
    widget.show()
    sys.exit(app.exec_())
